#include "oGamePreDefine.h"
#include "oGameAI.h"
#include "oGameTypes.h"
#include "oGameScene.h"

bool oDamageReaction::doAction()
{
	oUnit* unit = oAI::self();
	if (unit->hp <= 0.0f)
	{
		if (unit->getGroup() != GROUP_HIDE_ME && unit->getGroup() != GROUP_HIDE_ENEMY)
		{
			unit->setGroup(unit->getGroup() == GROUP_ME ? GROUP_HIDE_ME : GROUP_HIDE_ENEMY);
			unit->doIt(oID::ActionStop);
			unit->doIt(oID::ActionHit);
			unit->doIt(oID::ActionDie);
		}
	}
	else
	{
		if (oAI::getLastDeltaInstinctProperty() < 0.0f)
		{
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
			SimpleAudioEngine::sharedEngine()->playEffect("sound/hit.wav");
#endif
			unit->doIt(oID::ActionStop);
			unit->doIt(oID::ActionHit);
		}
	}
	return true;
}

bool hasAttackableEnemy(oUnit* unit)
{
	BOOST_FOREACH(oBody* body, unit->getAttackSensor()->getSensedBodies())
	{
		if (oSharedData.getRelation(body->getGroup(), unit->getGroup()) == e_enemy
			&& (body->getPositionX() > unit->getPositionX()) == unit->isFaceRight())
		{
			return true;
		}
	}
	return false;
}

bool oBunnyForwardReturn::doAction()
{
	oUnit* bunny = oAI::self();
	if (bunny->hp <= 0.0f)
	{
		return true;
	}
	if (oGameScene::isGameOver)
	{
		oAction* action = bunny->getCurrentAction();
		if (!action || action->getId() != oID::ActionIdle)
		{
			bunny->doIt(oID::ActionStop);
			bunny->doIt(oID::ActionIdle);
		}
		if (!oGameScene::isWin(bunny->getGroup()))
		{
			bunny->getModel()->setLook(oID::LookSad);
		}
		return true;
	}
	if (hasAttackableEnemy(bunny) && rand()%5 != 0)
	{
		bunny->doIt(oID::ActionMeleeAttack);
	}
	else
	{
		if (bunny->getPositionX() < 100.0f && !bunny->isFaceRight())
		{
			bunny->doIt(oID::ActionTurn);
		}
		else if (bunny->getPositionX() > 3990.0f && bunny->isFaceRight())
		{
			bunny->doIt(oID::ActionTurn);
		}
		if (!bunny->doIt(oID::ActionWalk))
		{
			bunny->doIt(oID::ActionIdle);
		}
	}
	return true;
}

bool oBunnySearchAttack::doAction()
{
	oUnit* bunny = oAI::self();
	if (bunny->hp <= 0.0f)
	{
		return true;
	}
	if (oGameScene::isGameOver)
	{
		oAction* action = bunny->getCurrentAction();
		if (!action || action->getId() != oID::ActionIdle)
		{
			bunny->doIt(oID::ActionStop);
			bunny->doIt(oID::ActionIdle);
		}
		if (!oGameScene::isWin(bunny->getGroup()))
		{
			bunny->getModel()->setLook(oID::LookSad);
		}
		return true;
	}
	if (hasAttackableEnemy(bunny) && rand()%5 != 0)
	{
		bunny->doIt(oID::ActionMeleeAttack);
	}
	else
	{
		oUnit* hero = bunny->getGroup() == GROUP_ME ? oGameScene::heroEnemy : oGameScene::heroMe;
		if (hero && hero->hp > 0.0f)
		{
			if ((hero->getPositionX() < bunny->getPositionX()) == bunny->isFaceRight())
			{
				bunny->doIt(oID::ActionTurn);
			}
			if (!bunny->doIt(oID::ActionWalk))
			{
				bunny->doIt(oID::ActionIdle);
			}
		}
		else
		{
			bunny->doIt(oID::ActionIdle);
		}
	}
	return true;
}

bool oBunnyForwardJump::doAction()
{
	oUnit* bunny = oAI::self();
	if (bunny->hp <= 0.0f)
	{
		return true;
	}
	if (oGameScene::isGameOver)
	{
		oAction* action = bunny->getCurrentAction();
		if (!action || action->getId() != oID::ActionIdle)
		{
			bunny->doIt(oID::ActionStop);
			bunny->doIt(oID::ActionIdle);
		}
		if (!oGameScene::isWin(bunny->getGroup()))
		{
			bunny->getModel()->setLook(oID::LookSad);
		}
		return true;
	}
	if (hasAttackableEnemy(bunny) && rand()%5 != 0)
	{
		bunny->doIt(oID::ActionMeleeAttack);
	}
	else
	{
		if (bunny->getPositionX() < 100.0f && !bunny->isFaceRight())
		{
			bunny->doIt(oID::ActionTurn);
		}
		else if (bunny->getPositionX() > 3990.0f && bunny->isFaceRight())
		{
			bunny->doIt(oID::ActionTurn);
		}
		if (!bunny->doIt(oID::ActionWalk))
		{
			bunny->doIt(oID::ActionIdle);
		}
		if (rand()%10 == 0)
		{
			oAI::self()->doIt(oID::ActionJump);
		}
	}
	return true;
}

bool oBunnySwitcher::doAction()
{
	oUnit* bunny = oAI::self();
	if (bunny->hp <= 0.0f)
	{
		return true;
	}
	if (oGameScene::isGameOver)
	{
		oAction* action = bunny->getCurrentAction();
		if (!action || action->getId() != oID::ActionIdle)
		{
			bunny->doIt(oID::ActionStop);
			bunny->doIt(oID::ActionIdle);
		}
		if (!oGameScene::isWin(bunny->getGroup()))
		{
			bunny->getModel()->setLook(oID::LookSad);
		}
		return true;
	}
	if (hasAttackableEnemy(bunny) && rand()%5 != 0)
	{
		bunny->doIt(oID::ActionMeleeAttack);
	}
	else
	{
		bool& isAttacked = bunny->getGroup() == GROUP_ME ? oGameScene::isMeAttacked : oGameScene::isEnemyAttacked;
		int bunnyCount = bunny->getGroup() == GROUP_ME ? oGameScene::bunnyMeCount : oGameScene::bunnyEnemyCount;
		float switchId = (float)oGetSwitchTag(bunny->properties[oStr::IsAtSwitch]);
		if (switchId > 0.0f && oGameScene::getMana(bunny->getGroup()) >= switchId)
		{
			if (switchId == (float)TAG_SWITCHG && !isAttacked)
			{
				bunny->doIt(oID::ActionIdle);
			}
			else if (switchId == (float)TAG_SWITCH && bunnyCount >= MAX_BUNNY)
			{
				bunny->doIt(oID::ActionIdle);
			}
			else
			{
				isAttacked = false;
				oGameScene::addMana(bunny->getGroup(), -switchId);
				bunny->doIt(ACTION_ROLE_SWITCH);
			}
		}
		else
		{
			bunny->doIt(oID::ActionIdle);
		}
	}
	return true;
}

bool oHeroControl::doAction()
{
	oUnit* unit = oAI::self();
	if (unit->hp <= 0.0f)
	{
		return true;
	}
	bool keyPressed = false;
	if (oKeyboard::isKeyPressed(GAME_KEY_F) && !oGameScene::isGameOver)
	{
		keyPressed = true;
		float switchId = (float)oGetSwitchTag(unit->properties[oStr::IsAtSwitch]);
		if (switchId > 0.0f && oGameScene::getMana(unit->getGroup()) >= switchId)
		{
			if (!unit->doIt(ACTION_ROLE_SWITCH))
			{
				if (!unit->doIt(oID::ActionMeleeAttack))
				{
					unit->doIt(oID::ActionRangeAttack);
				}
			}
		}
		else if (!unit->doIt(oID::ActionMeleeAttack))
		{
			unit->doIt(oID::ActionRangeAttack);
		}
	}
	if (oKeyboard::isKeyPressed(GAME_KEY_LEFT))
	{
		keyPressed = true;
		if (unit->isFaceRight())
		{
			unit->doIt(oID::ActionTurn);
		}
		unit->doIt(oID::ActionWalk);
	}
	else if (oKeyboard::isKeyPressed(GAME_KEY_RIGHT))
	{
		keyPressed = true;
		if (!unit->isFaceRight())
		{
			unit->doIt(oID::ActionTurn);
		}
		unit->doIt(oID::ActionWalk);
	}
	if (oKeyboard::isKeyPressed(GAME_KEY_UP))
	{
		keyPressed = true;
		unit->doIt(oID::ActionJump);
	}
	if (unit->getCurrentAction())
	{
		if (!keyPressed && unit->getCurrentAction()->getId() == oID::ActionWalk)
		{
			unit->doIt(oID::ActionStop);
			unit->doIt(oID::ActionIdle);
		}
	}
	else
	{
		unit->doIt(oID::ActionIdle);
	}
	return true;
}

bool oHeroFight::doAction()
{
	oUnit* hero = oAI::self();
	if (hero->hp <= 0.0f)
	{
		return true;
	}
	if (oGameScene::isGameOver)
	{
		oAction* action = hero->getCurrentAction();
		if (!action || action->getId() != oID::ActionIdle)
		{
			hero->doIt(oID::ActionStop);
			hero->doIt(oID::ActionIdle);
		}
		if (!oGameScene::isWin(hero->getGroup()))
		{
			hero->getModel()->setLook(oID::LookSad);
		}
		return true;
	}
	if (hasAttackableEnemy(hero))
	{
		if (rand()%3 == 0)
		{
			hero->doIt(oID::ActionJump);
		}
		if (!hero->doIt(oID::ActionMeleeAttack))
		{
			hero->doIt(oID::ActionRangeAttack);
		}
	}
	else
	{
		oUnit* enemy = hero->getGroup() == GROUP_ME ? oGameScene::heroEnemy : oGameScene::heroMe;
		if (enemy && enemy->hp > 0.0f)
		{
			if ((enemy->getPositionX() < hero->getPositionX()) == hero->isFaceRight())
			{
				hero->doIt(oID::ActionTurn);
			}
		}
		else
		{
			if ((hero->getGroup() == GROUP_ME) != hero->isFaceRight())
			{
				hero->doIt(oID::ActionTurn);
			}
			if (hero->getPositionX() < 100.0f && !hero->isFaceRight())
			{
				hero->doIt(oID::ActionTurn);
			}
			else if (hero->getPositionX() > 3990.0f && hero->isFaceRight())
			{
				hero->doIt(oID::ActionTurn);
			}
		}
		if (!hero->doIt(oID::ActionWalk))
		{
			hero->doIt(oID::ActionIdle);
		}
		else
		{
			if (rand()%10 == 0)
			{
				hero->doIt(oID::ActionJump);
			}
		}
	}
	return true;
}

oGameAI::oGameAI()
{
	oAILeaf* leaf = new oDamageReaction();
	leaf->autorelease();
	damegeReaction = oInstinct::create("hp", leaf);
	damegeReaction->retain();
	bunnyForwardReturn = new oBunnyForwardReturn();
	bunnySearchAttack = new oBunnySearchAttack();
	bunnyForwardJump = new oBunnyForwardJump();
	bunnySwitcher = new oBunnySwitcher();
	heroControl = new oHeroControl();
	heroFight = new oHeroFight();
}
oGameAI::~oGameAI()
{
	CC_SAFE_RELEASE_NULL(damegeReaction);
	CC_SAFE_DELETE(bunnyForwardReturn);
	CC_SAFE_DELETE(bunnySearchAttack);
	CC_SAFE_DELETE(bunnyForwardJump);
	CC_SAFE_DELETE(bunnySwitcher);
	CC_SAFE_DELETE(heroControl);
}
oGameAI& oGameAI::sharedAI()
{
	static oGameAI ai;
	return ai;
}

oAILeaf* oGameAI::getRandomBunnyAI()
{
	static oAILeaf* leafs[] =
	{
		bunnyForwardReturn,
		bunnySearchAttack,
		bunnyForwardJump
	};
	return leafs[rand()%(sizeof(leafs)/sizeof(oAILeaf*))];
}
